package dk.twu.analyzer.core;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by Tao Wu on 19/04/2015.
 */
public class Window {
    private final LocalDateTime startTime;
    private final int windowSize;
    private final ChronoUnit unit;
    private final List<LocalDateTime> units;

    public Window(LocalDateTime startTime, ChronoUnit unit, int windowSize) {
        this.startTime = startTime;
        this.windowSize = windowSize;
        this.unit = unit;
        this.units = initUnits(startTime, unit, windowSize);
    }

    private List<LocalDateTime> initUnits(LocalDateTime startTime, ChronoUnit unit, int windowSize) {
        List<LocalDateTime> units = new ArrayList<>();
        for (int i = 0; i < windowSize; i++) {
            units.add(startTime.plus(i, unit));
        }
        return units;
    }

    public List<LocalDateTime> getUnits() {
        return units;
    }

    public double[] buildValue(Map<LocalDateTime, Double> valueMap) {
        int windowSize = this.getUnits().size();
        double[] values = new double[windowSize];
        double lastValue = Double.NaN;
        // Build vector from value map, fill empty ones with the last valid value
        for (int i = 0; i < windowSize; i++) {
            Double doubleValue = valueMap.get(this.getUnits().get(i));
            if (doubleValue != null) {
                values[i] = doubleValue;
                lastValue = doubleValue;
            } else {
                values[i] = lastValue;
            }
        }
        // Find the first not NaN value for replacement of NaN
        double firstNotNaN = Double.NaN;
        for (int i = 0; i < windowSize; i ++) {
            if (!Double.isNaN(values[i])) {
                firstNotNaN = values[i];
                break;
            }
        }
        // Replace NaN value with the first NaN value found
        if (!Double.isNaN(firstNotNaN)) {
            for (int i = 0; i < windowSize; i ++) {
                if (Double.isNaN(values[i])) {
                    values[i] = firstNotNaN;
                }
            }
        }
        return values;
    }

    public LocalDateTime getStartTime() {
        return startTime;
    }
}
